{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# softmax回归的从零开始实现",
   "id": "ab001b4505af6fb1"
  },
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-08-10T15:48:38.389282Z",
     "start_time": "2025-08-10T15:48:38.344243Z"
    }
   },
   "source": [
    "from typing import Union\n",
    "\n",
    "import torch\n",
    "import os\n",
    "\n",
    "from jedi.inference.gradual.typing import Callable\n",
    "\n",
    "import utils_09\n",
    "batch_size = 256\n",
    "train_iter, test_iter = utils_09.load_data_fashion_mnist(\n",
    "    batch_size,\n",
    "    cpu_workers=max(0, int(os.cpu_count() / 2) - 2)\n",
    ")"
   ],
   "outputs": [],
   "execution_count": 60
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T15:48:38.405508Z",
     "start_time": "2025-08-10T15:48:38.402508Z"
    }
   },
   "cell_type": "code",
   "source": [
    "num_inputs = 28**2\n",
    "num_outputs = 10\n",
    "W = torch.normal(\n",
    "    mean=0,\n",
    "    std=0.01,\n",
    "    size = (num_inputs,num_outputs),\n",
    "    requires_grad=True\n",
    ")\n",
    "b = torch.zeros(\n",
    "    num_outputs,\n",
    "    requires_grad=True\n",
    ")"
   ],
   "id": "14f7e4f69d92ab50",
   "outputs": [],
   "execution_count": 61
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T15:48:38.419195Z",
     "start_time": "2025-08-10T15:48:38.415196Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def softmax(X:torch.Tensor) -> torch.Tensor:\n",
    "    X_exp = torch.exp(X)\n",
    "    partition = X_exp.sum(1,keepdim=True)\n",
    "    return X_exp / partition"
   ],
   "id": "3f258ecff950b6c3",
   "outputs": [],
   "execution_count": 62
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T15:48:38.443336Z",
     "start_time": "2025-08-10T15:48:38.439456Z"
    }
   },
   "cell_type": "code",
   "source": [
    "## 测试下softmax对矩阵处理效果\n",
    "X = torch.normal(0,1,(2,5))\n",
    "print(softmax(X))"
   ],
   "id": "f260425dba790a50",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0.4137, 0.0920, 0.2046, 0.1914, 0.0983],\n",
      "        [0.3383, 0.1546, 0.2487, 0.1709, 0.0876]])\n"
     ]
    }
   ],
   "execution_count": 63
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T15:48:38.473818Z",
     "start_time": "2025-08-10T15:48:38.470722Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def net(X:torch.Tensor) -> torch.Tensor:\n",
    "    return softmax(\n",
    "        torch.matmul(\n",
    "            X.reshape(\n",
    "                (-1,W.shape[0])\n",
    "            ),\n",
    "            W\n",
    "        ) + b\n",
    "    )"
   ],
   "id": "e81e59b397f510c2",
   "outputs": [],
   "execution_count": 64
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T15:48:38.488718Z",
     "start_time": "2025-08-10T15:48:38.486323Z"
    }
   },
   "cell_type": "code",
   "source": [
    "y = torch.tensor([0,2])\n",
    "y_predict = torch.tensor([[0.1,0.7,0.1],[0.3,0.1,0.6]])"
   ],
   "id": "aec256172df4181",
   "outputs": [],
   "execution_count": 65
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T15:48:38.505022Z",
     "start_time": "2025-08-10T15:48:38.501811Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def cross_entropy(y_predict:torch.Tensor,y:torch.Tensor) -> torch.Tensor:\n",
    "    return -torch.log(\n",
    "        y_predict[range(len(y_predict)),y]\n",
    "    )\n"
   ],
   "id": "396bc0152a25b339",
   "outputs": [],
   "execution_count": 66
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T15:48:38.521308Z",
     "start_time": "2025-08-10T15:48:38.517890Z"
    }
   },
   "cell_type": "code",
   "source": "cross_entropy(y_predict,y)",
   "id": "dcb61491935310cf",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([2.3026, 0.5108])"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 67
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T15:48:38.538896Z",
     "start_time": "2025-08-10T15:48:38.535312Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def accuracy(y_predict:torch.Tensor,y:torch.Tensor) -> torch.Tensor:\n",
    "    if len(y_predict.shape) > 1 and y_predict.shape[1] > 1:\n",
    "        y_predict = y_predict.argmax(axis = 1) ## 这里是获取最大元素的索引，不是值！！\n",
    "    cmp = y_predict.type(y.dtype) == y\n",
    "    cmp.type(y.dtype) ## 将cmp的数据格式转为y的数据格式，未转换前是bool，转换后为integer\n",
    "    return float(cmp.sum())"
   ],
   "id": "9d2b5b99cf5c69cd",
   "outputs": [],
   "execution_count": 68
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T15:48:38.564320Z",
     "start_time": "2025-08-10T15:48:38.560315Z"
    }
   },
   "cell_type": "code",
   "source": "accuracy(y_predict,y) / len(y)",
   "id": "6afff714b3ceaff5",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.5"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 69
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T15:48:38.594334Z",
     "start_time": "2025-08-10T15:48:38.590359Z"
    }
   },
   "cell_type": "code",
   "source": [
    "class Accumulator:\n",
    "    def __init__(self,n):\n",
    "        self.data = [0.0] * n ##创建n个计数器\n",
    "    def add(self,*args):\n",
    "        self.data = [a + float(b) for a,b in zip(self.data,args)]\n",
    "    def __getitem__(self, idx):\n",
    "        return self.data[idx]\n",
    "def evaluate_accuracy(net:Union[Callable,torch.nn.Module],data_iter:torch.utils.data.DataLoader):\n",
    "    if isinstance(net,torch.nn.Module):##判断net是否为torch.nn.Module\n",
    "       net.eval()\n",
    "    metric = Accumulator(2)\n",
    "    for X,y in data_iter:\n",
    "        metric.add(\n",
    "            accuracy(\n",
    "                net(X),y\n",
    "            ),\n",
    "            y.numel()\n",
    "        )\n",
    "    return metric[0]/metric[1]"
   ],
   "id": "f4b20667bf42c28b",
   "outputs": [],
   "execution_count": 70
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T15:48:43.196038Z",
     "start_time": "2025-08-10T15:48:38.612338Z"
    }
   },
   "cell_type": "code",
   "source": "evaluate_accuracy(net,test_iter)",
   "id": "2928074b8e20d84",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.11071666666666667"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 71
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T15:48:43.221715Z",
     "start_time": "2025-08-10T15:48:43.218554Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def sgd(params,lr,batch_size):\n",
    "    with torch.no_grad():\n",
    "        for param in params:\n",
    "            param -= lr * param.grad / batch_size ## 使用学习率*梯度对权重和bias进行更新\n",
    "            param.grad.zero_()"
   ],
   "id": "b314bd6e19472f50",
   "outputs": [],
   "execution_count": 72
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T16:13:23.814985Z",
     "start_time": "2025-08-10T16:13:23.812296Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def updater(batch_size,lr=0.9):\n",
    "    return sgd([W,b],lr,batch_size)"
   ],
   "id": "3b16318cf0ace7af",
   "outputs": [],
   "execution_count": 95
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T15:59:23.083104Z",
     "start_time": "2025-08-10T15:59:23.079104Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def train_epoch_ch3(net,train_iter,loss,updater):\n",
    "    if isinstance(net,torch.nn.Module):\n",
    "        net.train()\n",
    "    metric = Accumulator(3)\n",
    "    for X,y in train_iter:\n",
    "        y_predict = net(X)\n",
    "        l = loss(y_predict,y)\n",
    "        if isinstance(updater,torch.optim.Optimizer):\n",
    "            updater.zero_grad()\n",
    "            l.mean().backward()\n",
    "            updater.step()\n",
    "        else:\n",
    "            l.sum().backward()\n",
    "            updater(X.shape[0])\n",
    "        metric.add(float(l.sum()),accuracy(y_predict,y),y.numel())\n",
    "    return metric[0]/metric[2],metric[1]/metric[2]"
   ],
   "id": "d4393d4d24c5fb5c",
   "outputs": [],
   "execution_count": 90
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T16:13:35.597945Z",
     "start_time": "2025-08-10T16:13:35.594946Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def train_ch3(net,train_iter,test_iter,loss,num_epochs,updater):\n",
    "    for epoch in range(num_epochs):\n",
    "        train_metric = train_epoch_ch3(net,train_iter,loss,updater)\n",
    "        test_acc = evaluate_accuracy(net,test_iter)\n",
    "        print(f\"epoch {epoch}, train loss : {train_metric[0]}, train acc : {train_metric[1]},test_acc : {test_acc}\")\n",
    "    train_loss, train_acc = train_metric\n",
    "\n"
   ],
   "id": "39390d435614a5e6",
   "outputs": [],
   "execution_count": 96
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-10T16:40:10.307049Z",
     "start_time": "2025-08-10T16:13:37.871132Z"
    }
   },
   "cell_type": "code",
   "source": [
    "num_epochs = 300\n",
    "train_ch3(net,train_iter,test_iter,cross_entropy,num_epochs,updater)"
   ],
   "id": "900629d57c054193",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 0, train loss : 2.2345729966481525, train acc : 0.7683666666666666,test_acc : 0.7084833333333334\n",
      "epoch 1, train loss : 1.5280860764821371, train acc : 0.8017333333333333,test_acc : 0.76815\n",
      "epoch 2, train loss : 1.3750387635548909, train acc : 0.8088833333333333,test_acc : 0.8178833333333333\n",
      "epoch 3, train loss : 1.418043671544393, train acc : 0.80575,test_acc : 0.7732833333333333\n",
      "epoch 4, train loss : 1.3491355158487957, train acc : 0.8092,test_acc : 0.77585\n",
      "epoch 5, train loss : 1.3022838208516438, train acc : 0.8145666666666667,test_acc : 0.8285333333333333\n",
      "epoch 6, train loss : 1.3087300903320314, train acc : 0.8136666666666666,test_acc : 0.7913666666666667\n",
      "epoch 7, train loss : 1.2087343175252279, train acc : 0.8191666666666667,test_acc : 0.7834\n",
      "epoch 8, train loss : 1.252823187637329, train acc : 0.8162666666666667,test_acc : 0.7774666666666666\n",
      "epoch 9, train loss : 1.2385344126383464, train acc : 0.8165,test_acc : 0.7481166666666667\n",
      "epoch 10, train loss : 1.2153609015146891, train acc : 0.8204833333333333,test_acc : 0.8227333333333333\n",
      "epoch 11, train loss : 1.3169346500396728, train acc : 0.8141833333333334,test_acc : 0.8101166666666667\n",
      "epoch 12, train loss : 1.254751636505127, train acc : 0.8183166666666667,test_acc : 0.81875\n",
      "epoch 13, train loss : 1.2195489504496257, train acc : 0.8202666666666667,test_acc : 0.8432\n",
      "epoch 14, train loss : 1.27267037525177, train acc : 0.8168666666666666,test_acc : 0.8308166666666666\n",
      "epoch 15, train loss : 1.244757190577189, train acc : 0.8196333333333333,test_acc : 0.8451333333333333\n",
      "epoch 16, train loss : 1.196902362950643, train acc : 0.8214,test_acc : 0.7346\n",
      "epoch 17, train loss : 1.2237168722788492, train acc : 0.82035,test_acc : 0.7780833333333333\n",
      "epoch 18, train loss : 1.2876752685546875, train acc : 0.81805,test_acc : 0.7814333333333333\n",
      "epoch 19, train loss : 1.1308091370900473, train acc : 0.8262833333333334,test_acc : 0.8262\n",
      "epoch 20, train loss : 1.1441679432551066, train acc : 0.8246833333333333,test_acc : 0.8479666666666666\n",
      "epoch 21, train loss : 1.2549955757141114, train acc : 0.8198,test_acc : 0.6962833333333334\n",
      "epoch 22, train loss : 1.2692552136739095, train acc : 0.8193166666666667,test_acc : 0.8216\n",
      "epoch 23, train loss : 1.2108607242584228, train acc : 0.8230333333333333,test_acc : 0.7785\n",
      "epoch 24, train loss : 1.2110524360020956, train acc : 0.8207666666666666,test_acc : 0.8629833333333333\n",
      "epoch 25, train loss : 1.2129704635620118, train acc : 0.8233833333333334,test_acc : 0.8268666666666666\n",
      "epoch 26, train loss : 1.1597034136454265, train acc : 0.8250666666666666,test_acc : 0.799\n",
      "epoch 27, train loss : 1.2323487756729126, train acc : 0.8213833333333334,test_acc : 0.8507\n",
      "epoch 28, train loss : 1.1936638320922852, train acc : 0.8223,test_acc : 0.8087\n",
      "epoch 29, train loss : 1.1782794246673585, train acc : 0.8247666666666666,test_acc : 0.82265\n",
      "epoch 30, train loss : 1.2232808203379313, train acc : 0.82055,test_acc : 0.85615\n",
      "epoch 31, train loss : 1.181319867769877, train acc : 0.8237833333333333,test_acc : 0.8267833333333333\n",
      "epoch 32, train loss : 1.196359712600708, train acc : 0.8235166666666667,test_acc : 0.8297666666666667\n",
      "epoch 33, train loss : 1.2018941038767497, train acc : 0.8207833333333333,test_acc : 0.7857333333333333\n",
      "epoch 34, train loss : 1.1337043671925862, train acc : 0.82655,test_acc : 0.8062333333333334\n",
      "epoch 35, train loss : 1.170639129257202, train acc : 0.82305,test_acc : 0.7935666666666666\n",
      "epoch 36, train loss : 1.1946370035807292, train acc : 0.8232333333333334,test_acc : 0.8029833333333334\n",
      "epoch 37, train loss : 1.1799196327845256, train acc : 0.8249,test_acc : 0.8417\n",
      "epoch 38, train loss : 1.1347084869384765, train acc : 0.82695,test_acc : 0.7878333333333334\n",
      "epoch 39, train loss : 1.1823473594665528, train acc : 0.8236833333333333,test_acc : 0.8373833333333334\n",
      "epoch 40, train loss : 1.1568372526804607, train acc : 0.8254333333333334,test_acc : 0.8179166666666666\n",
      "epoch 41, train loss : 1.1292121550242107, train acc : 0.8265166666666667,test_acc : 0.8097166666666666\n",
      "epoch 42, train loss : 1.11100403620402, train acc : 0.8275,test_acc : 0.8\n",
      "epoch 43, train loss : 1.1973709520975748, train acc : 0.8224,test_acc : 0.8232666666666667\n",
      "epoch 44, train loss : 1.1543798965454102, train acc : 0.8251,test_acc : 0.8039\n",
      "epoch 45, train loss : 1.1935578311920165, train acc : 0.824,test_acc : 0.8312166666666667\n",
      "epoch 46, train loss : 1.1762702382405599, train acc : 0.8259166666666666,test_acc : 0.7331166666666666\n",
      "epoch 47, train loss : 1.148367043685913, train acc : 0.826,test_acc : 0.8397166666666667\n",
      "epoch 48, train loss : 1.1348420369466146, train acc : 0.8272166666666667,test_acc : 0.8647\n",
      "epoch 49, train loss : 1.1495599934895833, train acc : 0.8280833333333333,test_acc : 0.8248166666666666\n",
      "epoch 50, train loss : 1.1679600382486979, train acc : 0.827,test_acc : 0.7935666666666666\n",
      "epoch 51, train loss : 1.1628055062611897, train acc : 0.8243666666666667,test_acc : 0.8513333333333334\n",
      "epoch 52, train loss : 1.08589303372701, train acc : 0.8286833333333333,test_acc : 0.8244666666666667\n",
      "epoch 53, train loss : 1.1269531416575114, train acc : 0.82795,test_acc : 0.8179666666666666\n",
      "epoch 54, train loss : 1.1846631800333658, train acc : 0.8250333333333333,test_acc : 0.8127333333333333\n",
      "epoch 55, train loss : 1.1183839537302653, train acc : 0.8284,test_acc : 0.8598166666666667\n",
      "epoch 56, train loss : 1.1333342770894368, train acc : 0.8281666666666667,test_acc : 0.8186333333333333\n",
      "epoch 57, train loss : 1.1496477063496908, train acc : 0.8264833333333333,test_acc : 0.8191166666666667\n",
      "epoch 58, train loss : 1.1870827414194742, train acc : 0.8232,test_acc : 0.8105166666666667\n",
      "epoch 59, train loss : 1.1313687662760417, train acc : 0.8300333333333333,test_acc : 0.86735\n",
      "epoch 60, train loss : 1.1035753116607665, train acc : 0.82695,test_acc : 0.8004166666666667\n",
      "epoch 61, train loss : 1.1539046944936115, train acc : 0.8269,test_acc : 0.8204666666666667\n",
      "epoch 62, train loss : 1.1759815250396728, train acc : 0.8253666666666667,test_acc : 0.7608\n",
      "epoch 63, train loss : 1.1724692024230956, train acc : 0.8268166666666666,test_acc : 0.8616833333333334\n",
      "epoch 64, train loss : 1.1369194938659668, train acc : 0.8280333333333333,test_acc : 0.7987166666666666\n",
      "epoch 65, train loss : 1.1668227767944337, train acc : 0.8261833333333334,test_acc : 0.7849\n",
      "epoch 66, train loss : 1.1327783252716064, train acc : 0.8308166666666666,test_acc : 0.7758333333333334\n",
      "epoch 67, train loss : 1.141748353068034, train acc : 0.8259,test_acc : 0.8139166666666666\n",
      "epoch 68, train loss : 1.1895886184692384, train acc : 0.8281,test_acc : 0.8385333333333334\n",
      "epoch 69, train loss : 1.13933616549174, train acc : 0.8276666666666667,test_acc : 0.7062833333333334\n",
      "epoch 70, train loss : 1.118357053120931, train acc : 0.8284666666666667,test_acc : 0.7967\n",
      "epoch 71, train loss : 1.1170298406600951, train acc : 0.8286333333333333,test_acc : 0.8335833333333333\n",
      "epoch 72, train loss : 1.122247758102417, train acc : 0.8287666666666667,test_acc : 0.8565166666666667\n",
      "epoch 73, train loss : 1.1026179101308187, train acc : 0.8306666666666667,test_acc : 0.7902666666666667\n",
      "epoch 74, train loss : 1.1287925936381022, train acc : 0.8258,test_acc : 0.7957166666666666\n",
      "epoch 75, train loss : 1.068436606089274, train acc : 0.8316833333333333,test_acc : 0.7656666666666667\n",
      "epoch 76, train loss : 1.1594749996185303, train acc : 0.8259833333333333,test_acc : 0.8386333333333333\n",
      "epoch 77, train loss : 1.166166806793213, train acc : 0.8272333333333334,test_acc : 0.8329166666666666\n",
      "epoch 78, train loss : 1.109585427093506, train acc : 0.8296333333333333,test_acc : 0.8089666666666666\n",
      "epoch 79, train loss : 1.1385903137207032, train acc : 0.8277666666666667,test_acc : 0.8389666666666666\n",
      "epoch 80, train loss : 1.1531370164235433, train acc : 0.8276666666666667,test_acc : 0.8430333333333333\n",
      "epoch 81, train loss : 1.134654934946696, train acc : 0.8259666666666666,test_acc : 0.8497333333333333\n",
      "epoch 82, train loss : 1.097066785812378, train acc : 0.8298333333333333,test_acc : 0.7161666666666666\n",
      "epoch 83, train loss : 1.1129395745595296, train acc : 0.8311833333333334,test_acc : 0.8434166666666667\n",
      "epoch 84, train loss : 1.1031934352874755, train acc : 0.8305833333333333,test_acc : 0.8669333333333333\n",
      "epoch 85, train loss : 1.1099728211720785, train acc : 0.82795,test_acc : 0.7777666666666667\n",
      "epoch 86, train loss : 1.2035348160425823, train acc : 0.8244333333333334,test_acc : 0.8649333333333333\n",
      "epoch 87, train loss : 1.140254721069336, train acc : 0.8278833333333333,test_acc : 0.8544333333333334\n",
      "epoch 88, train loss : 1.1531015989939373, train acc : 0.8286,test_acc : 0.85865\n",
      "epoch 89, train loss : 1.0478080790201822, train acc : 0.83365,test_acc : 0.805\n",
      "epoch 90, train loss : 1.122497431310018, train acc : 0.8282333333333334,test_acc : 0.8241166666666667\n",
      "epoch 91, train loss : 1.1295975362141928, train acc : 0.8296833333333333,test_acc : 0.8380666666666666\n",
      "epoch 92, train loss : 1.1431245321909587, train acc : 0.8271833333333334,test_acc : 0.8484666666666667\n",
      "epoch 93, train loss : 1.090147644551595, train acc : 0.8312166666666667,test_acc : 0.79245\n",
      "epoch 94, train loss : 1.145539614868164, train acc : 0.8272166666666667,test_acc : 0.7915666666666666\n",
      "epoch 95, train loss : 1.1453023723602296, train acc : 0.8277,test_acc : 0.8516\n",
      "epoch 96, train loss : 1.1289167509714761, train acc : 0.8296333333333333,test_acc : 0.80875\n",
      "epoch 97, train loss : 1.0861894278208415, train acc : 0.83135,test_acc : 0.8019\n",
      "epoch 98, train loss : 1.1814937817891438, train acc : 0.8257166666666667,test_acc : 0.8646166666666667\n",
      "epoch 99, train loss : 1.1168862775802613, train acc : 0.82995,test_acc : 0.8677\n",
      "epoch 100, train loss : 1.094246068318685, train acc : 0.8293333333333334,test_acc : 0.8685\n",
      "epoch 101, train loss : 1.031945190302531, train acc : 0.8343,test_acc : 0.8532\n",
      "epoch 102, train loss : 1.1145887851715088, train acc : 0.8296166666666667,test_acc : 0.7579833333333333\n",
      "epoch 103, train loss : 1.1977339839935304, train acc : 0.8269333333333333,test_acc : 0.7947833333333333\n",
      "epoch 104, train loss : 1.1143692375183105, train acc : 0.8304,test_acc : 0.8562\n",
      "epoch 105, train loss : 1.1703889769236246, train acc : 0.8280833333333333,test_acc : 0.7865166666666666\n",
      "epoch 106, train loss : 1.1692984911600748, train acc : 0.8281166666666666,test_acc : 0.8473\n",
      "epoch 107, train loss : 1.1029132418314616, train acc : 0.8302833333333334,test_acc : 0.76385\n",
      "epoch 108, train loss : 1.18011162109375, train acc : 0.8269333333333333,test_acc : 0.8566\n",
      "epoch 109, train loss : 1.0561493775685629, train acc : 0.8340833333333333,test_acc : 0.6502\n",
      "epoch 110, train loss : 1.1547741731007894, train acc : 0.8283833333333334,test_acc : 0.83775\n",
      "epoch 111, train loss : 1.0841661651611327, train acc : 0.8325333333333333,test_acc : 0.7276166666666667\n",
      "epoch 112, train loss : 1.1563973140716552, train acc : 0.8289833333333333,test_acc : 0.8113333333333334\n",
      "epoch 113, train loss : 1.0846161535898844, train acc : 0.8323333333333334,test_acc : 0.7747833333333334\n",
      "epoch 114, train loss : 1.0970462069193523, train acc : 0.82985,test_acc : 0.78145\n",
      "epoch 115, train loss : 1.0834250165303547, train acc : 0.8307166666666667,test_acc : 0.8004166666666667\n",
      "epoch 116, train loss : 1.1051214623769123, train acc : 0.8311333333333333,test_acc : 0.7471333333333333\n",
      "epoch 117, train loss : 1.1165304850260416, train acc : 0.8295833333333333,test_acc : 0.8637833333333333\n",
      "epoch 118, train loss : 1.1237853578567505, train acc : 0.8292666666666667,test_acc : 0.7794\n",
      "epoch 119, train loss : 1.193097529411316, train acc : 0.8244333333333334,test_acc : 0.8484666666666667\n",
      "epoch 120, train loss : 1.1276794114430746, train acc : 0.8322666666666667,test_acc : 0.8472666666666666\n",
      "epoch 121, train loss : 1.1480399424235026, train acc : 0.82755,test_acc : 0.8601666666666666\n",
      "epoch 122, train loss : 1.0813990999857586, train acc : 0.83195,test_acc : 0.8581833333333333\n",
      "epoch 123, train loss : 1.1598147521972657, train acc : 0.82875,test_acc : 0.6550666666666667\n",
      "epoch 124, train loss : 1.1839196352640788, train acc : 0.8288833333333333,test_acc : 0.8559833333333333\n",
      "epoch 125, train loss : 1.123399091720581, train acc : 0.8303333333333334,test_acc : 0.8152333333333334\n",
      "epoch 126, train loss : 1.0755806303660076, train acc : 0.8327666666666667,test_acc : 0.7683666666666666\n",
      "epoch 127, train loss : 1.107853190867106, train acc : 0.83135,test_acc : 0.8029166666666666\n",
      "epoch 128, train loss : 1.1218453164418538, train acc : 0.8315166666666667,test_acc : 0.7945666666666666\n",
      "epoch 129, train loss : 1.0933191697438558, train acc : 0.8307,test_acc : 0.8388333333333333\n",
      "epoch 130, train loss : 1.099416026878357, train acc : 0.8324833333333334,test_acc : 0.7909833333333334\n",
      "epoch 131, train loss : 1.145905399576823, train acc : 0.8288666666666666,test_acc : 0.8564\n",
      "epoch 132, train loss : 1.13702354443868, train acc : 0.8313,test_acc : 0.6782\n",
      "epoch 133, train loss : 1.0903180723190307, train acc : 0.8308333333333333,test_acc : 0.8244666666666667\n",
      "epoch 134, train loss : 1.11589895362854, train acc : 0.8316333333333333,test_acc : 0.8641\n",
      "epoch 135, train loss : 1.1200062149047851, train acc : 0.8291166666666666,test_acc : 0.8021\n",
      "epoch 136, train loss : nan, train acc : 0.77935,test_acc : 0.1\n",
      "epoch 137, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 138, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 139, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 140, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 141, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 142, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 143, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 144, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 145, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 146, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 147, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 148, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 149, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 150, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 151, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 152, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 153, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 154, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 155, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 156, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 157, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 158, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 159, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 160, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 161, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 162, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 163, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 164, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 165, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 166, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 167, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 168, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 169, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 170, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 171, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 172, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 173, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 174, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 175, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 176, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 177, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 178, train loss : nan, train acc : 0.1,test_acc : 0.1\n",
      "epoch 179, train loss : nan, train acc : 0.1,test_acc : 0.1\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001B[31m---------------------------------------------------------------------------\u001B[39m",
      "\u001B[31mKeyboardInterrupt\u001B[39m                         Traceback (most recent call last)",
      "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[97]\u001B[39m\u001B[32m, line 2\u001B[39m\n\u001B[32m      1\u001B[39m num_epochs = \u001B[32m300\u001B[39m\n\u001B[32m----> \u001B[39m\u001B[32m2\u001B[39m \u001B[43mtrain_ch3\u001B[49m\u001B[43m(\u001B[49m\u001B[43mnet\u001B[49m\u001B[43m,\u001B[49m\u001B[43mtrain_iter\u001B[49m\u001B[43m,\u001B[49m\u001B[43mtest_iter\u001B[49m\u001B[43m,\u001B[49m\u001B[43mcross_entropy\u001B[49m\u001B[43m,\u001B[49m\u001B[43mnum_epochs\u001B[49m\u001B[43m,\u001B[49m\u001B[43mupdater\u001B[49m\u001B[43m)\u001B[49m\n",
      "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[96]\u001B[39m\u001B[32m, line 3\u001B[39m, in \u001B[36mtrain_ch3\u001B[39m\u001B[34m(net, train_iter, test_iter, loss, num_epochs, updater)\u001B[39m\n\u001B[32m      1\u001B[39m \u001B[38;5;28;01mdef\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34mtrain_ch3\u001B[39m(net,train_iter,test_iter,loss,num_epochs,updater):\n\u001B[32m      2\u001B[39m     \u001B[38;5;28;01mfor\u001B[39;00m epoch \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mrange\u001B[39m(num_epochs):\n\u001B[32m----> \u001B[39m\u001B[32m3\u001B[39m         train_metric = \u001B[43mtrain_epoch_ch3\u001B[49m\u001B[43m(\u001B[49m\u001B[43mnet\u001B[49m\u001B[43m,\u001B[49m\u001B[43mtrain_iter\u001B[49m\u001B[43m,\u001B[49m\u001B[43mloss\u001B[49m\u001B[43m,\u001B[49m\u001B[43mupdater\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m      4\u001B[39m         test_acc = evaluate_accuracy(net,test_iter)\n\u001B[32m      5\u001B[39m         \u001B[38;5;28mprint\u001B[39m(\u001B[33mf\u001B[39m\u001B[33m\"\u001B[39m\u001B[33mepoch \u001B[39m\u001B[38;5;132;01m{\u001B[39;00mepoch\u001B[38;5;132;01m}\u001B[39;00m\u001B[33m, train loss : \u001B[39m\u001B[38;5;132;01m{\u001B[39;00mtrain_metric[\u001B[32m0\u001B[39m]\u001B[38;5;132;01m}\u001B[39;00m\u001B[33m, train acc : \u001B[39m\u001B[38;5;132;01m{\u001B[39;00mtrain_metric[\u001B[32m1\u001B[39m]\u001B[38;5;132;01m}\u001B[39;00m\u001B[33m,test_acc : \u001B[39m\u001B[38;5;132;01m{\u001B[39;00mtest_acc\u001B[38;5;132;01m}\u001B[39;00m\u001B[33m\"\u001B[39m)\n",
      "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[90]\u001B[39m\u001B[32m, line 5\u001B[39m, in \u001B[36mtrain_epoch_ch3\u001B[39m\u001B[34m(net, train_iter, loss, updater)\u001B[39m\n\u001B[32m      3\u001B[39m     net.train()\n\u001B[32m      4\u001B[39m metric = Accumulator(\u001B[32m3\u001B[39m)\n\u001B[32m----> \u001B[39m\u001B[32m5\u001B[39m \u001B[43m\u001B[49m\u001B[38;5;28;43;01mfor\u001B[39;49;00m\u001B[43m \u001B[49m\u001B[43mX\u001B[49m\u001B[43m,\u001B[49m\u001B[43my\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;129;43;01min\u001B[39;49;00m\u001B[43m \u001B[49m\u001B[43mtrain_iter\u001B[49m\u001B[43m:\u001B[49m\n\u001B[32m      6\u001B[39m \u001B[43m    \u001B[49m\u001B[43my_predict\u001B[49m\u001B[43m \u001B[49m\u001B[43m=\u001B[49m\u001B[43m \u001B[49m\u001B[43mnet\u001B[49m\u001B[43m(\u001B[49m\u001B[43mX\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m      7\u001B[39m \u001B[43m    \u001B[49m\u001B[43ml\u001B[49m\u001B[43m \u001B[49m\u001B[43m=\u001B[49m\u001B[43m \u001B[49m\u001B[43mloss\u001B[49m\u001B[43m(\u001B[49m\u001B[43my_predict\u001B[49m\u001B[43m,\u001B[49m\u001B[43my\u001B[49m\u001B[43m)\u001B[49m\n",
      "\u001B[36mFile \u001B[39m\u001B[32m~\\.local\\share\\mamba\\envs\\d2l\\Lib\\site-packages\\torch\\utils\\data\\dataloader.py:733\u001B[39m, in \u001B[36m_BaseDataLoaderIter.__next__\u001B[39m\u001B[34m(self)\u001B[39m\n\u001B[32m    730\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28mself\u001B[39m._sampler_iter \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n\u001B[32m    731\u001B[39m     \u001B[38;5;66;03m# TODO(https://github.com/pytorch/pytorch/issues/76750)\u001B[39;00m\n\u001B[32m    732\u001B[39m     \u001B[38;5;28mself\u001B[39m._reset()  \u001B[38;5;66;03m# type: ignore[call-arg]\u001B[39;00m\n\u001B[32m--> \u001B[39m\u001B[32m733\u001B[39m data = \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_next_data\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m    734\u001B[39m \u001B[38;5;28mself\u001B[39m._num_yielded += \u001B[32m1\u001B[39m\n\u001B[32m    735\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m (\n\u001B[32m    736\u001B[39m     \u001B[38;5;28mself\u001B[39m._dataset_kind == _DatasetKind.Iterable\n\u001B[32m    737\u001B[39m     \u001B[38;5;129;01mand\u001B[39;00m \u001B[38;5;28mself\u001B[39m._IterableDataset_len_called \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[32m    738\u001B[39m     \u001B[38;5;129;01mand\u001B[39;00m \u001B[38;5;28mself\u001B[39m._num_yielded > \u001B[38;5;28mself\u001B[39m._IterableDataset_len_called\n\u001B[32m    739\u001B[39m ):\n",
      "\u001B[36mFile \u001B[39m\u001B[32m~\\.local\\share\\mamba\\envs\\d2l\\Lib\\site-packages\\torch\\utils\\data\\dataloader.py:1479\u001B[39m, in \u001B[36m_MultiProcessingDataLoaderIter._next_data\u001B[39m\u001B[34m(self)\u001B[39m\n\u001B[32m   1476\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m   1477\u001B[39m     \u001B[38;5;66;03m# no valid `self._rcvd_idx` is found (i.e., didn't break)\u001B[39;00m\n\u001B[32m   1478\u001B[39m     \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28mself\u001B[39m._persistent_workers:\n\u001B[32m-> \u001B[39m\u001B[32m1479\u001B[39m         \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_shutdown_workers\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m   1480\u001B[39m     \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mStopIteration\u001B[39;00m\n\u001B[32m   1482\u001B[39m \u001B[38;5;66;03m# Now `self._rcvd_idx` is the batch index we want to fetch\u001B[39;00m\n\u001B[32m   1483\u001B[39m \n\u001B[32m   1484\u001B[39m \u001B[38;5;66;03m# Check if the next sample has already been generated\u001B[39;00m\n",
      "\u001B[36mFile \u001B[39m\u001B[32m~\\.local\\share\\mamba\\envs\\d2l\\Lib\\site-packages\\torch\\utils\\data\\dataloader.py:1627\u001B[39m, in \u001B[36m_MultiProcessingDataLoaderIter._shutdown_workers\u001B[39m\u001B[34m(self)\u001B[39m\n\u001B[32m   1622\u001B[39m         \u001B[38;5;28mself\u001B[39m._mark_worker_as_unavailable(worker_id, shutdown=\u001B[38;5;28;01mTrue\u001B[39;00m)\n\u001B[32m   1623\u001B[39m \u001B[38;5;28;01mfor\u001B[39;00m w \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mself\u001B[39m._workers:\n\u001B[32m   1624\u001B[39m     \u001B[38;5;66;03m# We should be able to join here, but in case anything went\u001B[39;00m\n\u001B[32m   1625\u001B[39m     \u001B[38;5;66;03m# wrong, we set a timeout and if the workers fail to join,\u001B[39;00m\n\u001B[32m   1626\u001B[39m     \u001B[38;5;66;03m# they are killed in the `finally` block.\u001B[39;00m\n\u001B[32m-> \u001B[39m\u001B[32m1627\u001B[39m     \u001B[43mw\u001B[49m\u001B[43m.\u001B[49m\u001B[43mjoin\u001B[49m\u001B[43m(\u001B[49m\u001B[43mtimeout\u001B[49m\u001B[43m=\u001B[49m\u001B[43m_utils\u001B[49m\u001B[43m.\u001B[49m\u001B[43mMP_STATUS_CHECK_INTERVAL\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m   1628\u001B[39m \u001B[38;5;28;01mfor\u001B[39;00m q \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mself\u001B[39m._index_queues:\n\u001B[32m   1629\u001B[39m     q.cancel_join_thread()\n",
      "\u001B[36mFile \u001B[39m\u001B[32m~\\.local\\share\\mamba\\envs\\d2l\\Lib\\multiprocessing\\process.py:149\u001B[39m, in \u001B[36mBaseProcess.join\u001B[39m\u001B[34m(self, timeout)\u001B[39m\n\u001B[32m    147\u001B[39m \u001B[38;5;28;01massert\u001B[39;00m \u001B[38;5;28mself\u001B[39m._parent_pid == os.getpid(), \u001B[33m'\u001B[39m\u001B[33mcan only join a child process\u001B[39m\u001B[33m'\u001B[39m\n\u001B[32m    148\u001B[39m \u001B[38;5;28;01massert\u001B[39;00m \u001B[38;5;28mself\u001B[39m._popen \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m, \u001B[33m'\u001B[39m\u001B[33mcan only join a started process\u001B[39m\u001B[33m'\u001B[39m\n\u001B[32m--> \u001B[39m\u001B[32m149\u001B[39m res = \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_popen\u001B[49m\u001B[43m.\u001B[49m\u001B[43mwait\u001B[49m\u001B[43m(\u001B[49m\u001B[43mtimeout\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m    150\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m res \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n\u001B[32m    151\u001B[39m     _children.discard(\u001B[38;5;28mself\u001B[39m)\n",
      "\u001B[36mFile \u001B[39m\u001B[32m~\\.local\\share\\mamba\\envs\\d2l\\Lib\\multiprocessing\\popen_spawn_win32.py:112\u001B[39m, in \u001B[36mPopen.wait\u001B[39m\u001B[34m(self, timeout)\u001B[39m\n\u001B[32m    109\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m    110\u001B[39m     msecs = \u001B[38;5;28mmax\u001B[39m(\u001B[32m0\u001B[39m, \u001B[38;5;28mint\u001B[39m(timeout * \u001B[32m1000\u001B[39m + \u001B[32m0.5\u001B[39m))\n\u001B[32m--> \u001B[39m\u001B[32m112\u001B[39m res = \u001B[43m_winapi\u001B[49m\u001B[43m.\u001B[49m\u001B[43mWaitForSingleObject\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;28;43mint\u001B[39;49m\u001B[43m(\u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_handle\u001B[49m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mmsecs\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m    113\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m res == _winapi.WAIT_OBJECT_0:\n\u001B[32m    114\u001B[39m     code = _winapi.GetExitCodeProcess(\u001B[38;5;28mself\u001B[39m._handle)\n",
      "\u001B[31mKeyboardInterrupt\u001B[39m: "
     ]
    }
   ],
   "execution_count": 97
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
